#include"ThreadPool.h"
#include<iostream>
#include<string.h>
#include<string>
#include<unistd.h>
#include<pthread.h>
#include<cstring>
ThreadPool::ThreadPool(int min,int max)
{
	//实例化任务队列
	do
	{
		taskQ = new TaskQueue;
		if(taskQ==nullptr)
                {
                        std::cout<<"new is faile"<<std::endl;
                        break;
                }

		threadIDs = new pthread_t[max];
		if(threadIDs==nullptr)
		{
			std::cout<<"new is faile"<<std::endl;
			break;
		}

		memset(threadIDs,0,sizeof(pthread_t)*max);
		minNum = min;
		maxNum = max;
		busyNum = 0;
		liveNum = min;
		exitNum = 0;

		if(pthread_mutex_init(&mutexPool,NULL) != 0 || pthread_cond_init(&notEmpty,NULL)!=0)
		{
			std::cout<<"mutex and condition init fail"<<std::endl;
			break;
		}

		shutdown=false;

		//创建线程
		pthread_create(&managerID,nullptr,manager,this);
		for(int i = 0;i<min;i++)
		{
			pthread_create(&threadIDs[i],nullptr,worker,this);
		}

		return;
	}while(0);

	//释放资源
	if(threadIDs) delete []threadIDs;
	if(taskQ) delete taskQ;
}


ThreadPool::~ThreadPool()
{

	//关闭线程池
	shutdown=true;
	//阻塞回收管理者线程
	pthread_join(managerID,NULL);
	//唤醒阻塞的消费者线程
	for(int i=0;i<liveNum;i++){
		pthread_cond_signal(&notEmpty);
	}
        //释放堆内存
	if(taskQ)
	{
		delete taskQ;
	}

	if(threadIDs)
	{
		delete[] threadIDs;
	}

	pthread_mutex_destroy(&mutexPool);
	pthread_cond_destroy(&notEmpty);

}



void* ThreadPool::worker(void* arg)
{
	ThreadPool* pool = static_cast<ThreadPool*>(arg);//static_cast<int>强制转换为int

	while(true)
	{
		pthread_mutex_lock(&pool->mutexPool);
		//当前队列是否为空
		while(pool->taskQ->taskNumber() == 0 && !pool->shutdown)
		{

			//阻塞工作线程
			pthread_cond_wait(&pool->notEmpty,&pool->mutexPool);

			//判断是否销毁线程
			if(pool->exitNum>0)
			{
				pool->exitNum--;
				if(pool->liveNum > pool->minNum)
				{
					pool->liveNum--;
					pthread_mutex_unlock(&pool->mutexPool);
			        	pool->threadExit();
				}
			}
		}


        	//判断线程池是否被关闭
        	if(pool->shutdown)
	        {
	        	pthread_mutex_unlock(&pool->mutexPool);
	        	pool->threadExit();
        	}

        	//从任务队列取出一个任务
        	Task task=pool->taskQ->takeTask();
 
        	//移动头节点
        	//解锁
         	pool->busyNum++;
         	pthread_mutex_unlock(&pool->mutexPool);

        	std::cout<<"thread"<<std::to_string(pthread_self())<<"start working..."<<std::endl;

	        task.function(task.arg);
                delete task.arg;
        	task.arg=nullptr;

        	std::cout<<"thread"<<std::to_string(pthread_self())<<"start working..."<<std::endl;

        	pthread_mutex_lock(&pool->mutexPool);
        	pool->busyNum--;
        	pthread_mutex_unlock(&pool->mutexPool);
	}
	return nullptr;
}


void* ThreadPool::manager(void* arg)
{
	ThreadPool* pool=static_cast<ThreadPool*>(arg);

	while(!pool->shutdown)
	{
		sleep(3);

		//取出线程池中任务的数量和当前线程的数量
		////取出忙的线程数量

		pthread_mutex_lock(&pool->mutexPool);
		int queueSize=pool->taskQ->taskNumber();
		int liveNum=pool->liveNum;
		int busyNum=pool->busyNum;
		pthread_mutex_unlock(&pool->mutexPool);

		//添加线程
		//任务个数>存活线程个数 &&存活线程数 < 最大线程数
		if(queueSize>liveNum && liveNum<pool->maxNum);
		{
		        pthread_mutex_lock(&pool->mutexPool);
			int counter=0;
			for(int i=0;i<pool->maxNum && counter<NUMBER && pool->liveNum<pool->maxNum;i++)
			{
				if(pool->threadIDs[i]==0)
				{
					pthread_create(&pool->threadIDs[i],nullptr,worker,pool);
					counter++;
					pool->liveNum++;
				}
			}
			pthread_mutex_unlock(&pool->mutexPool);
		}  


		//销毁线程
		//忙的线程*2 <存活的线程数 && 存活的线程 > 最小线程

		if(busyNum*2 < liveNum && liveNum > pool->minNum)
		{
			 pthread_mutex_lock(&pool->mutexPool);
			 pool->exitNum=NUMBER;
			 pthread_mutex_unlock(&pool->mutexPool);

			 //让工作的线程自杀
			 for(int i=0;i<NUMBER;i++)
			 {
				 pthread_cond_signal(&pool->notEmpty);
			 }
		}
	}
	return nullptr;
}


void ThreadPool::threadExit()
{
	pthread_t tid=pthread_self();
	for(int i =0; i < maxNum; i++)
	{
		if(threadIDs[i] == tid)
		{
			threadIDs[i]=0;
			std::cout<<"threadExit() called,"<<std::to_string(tid)<<"exiting..."<<std::endl;
			break;
		}
	}
	pthread_exit(NULL);
}


void ThreadPool::addTask(Task task)
{

	if(shutdown)
	{
		return;
	}

	//添加任务
	taskQ->addTask(task);
	pthread_cond_signal(&notEmpty);
}

int ThreadPool::getBusyNum()
{
	pthread_mutex_lock(&mutexPool);
	int busyNum = this->busyNum;
	pthread_mutex_unlock(&mutexPool);
	return busyNum;
}

int ThreadPool::getAliveNum()
{
	 pthread_mutex_lock(&mutexPool);
	 int aliveNum = this->liveNum;
	 pthread_mutex_unlock(&mutexPool);
	 return aliveNum;
}















